import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer'
// 模型加载器
import { loadManager } from '../model/loadManager'
import { City } from '../model/City'
import { Ship } from '../model/Ship'
import { Sky } from '../environment/Sky'
import { EffectManager } from '../utils/EffectManager'
import { ClickHandler } from '../utils/ClickHandler'
import { Fly } from '../model/Fly'
import { EventBus } from '@/utils/EventBus'
import { DataManager } from '../utils/DataManager'
import { modifySelectCityMaterial } from '../shader/modifyCityMaterial'
let scene, camera, renderer, control, css2Renderer

// 初始化 3d 基本环境
function init() {
  scene = new THREE.Scene()
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10000)
  camera.position.set(-148, 55, -101)

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(window.innerWidth, window.innerHeight)

  // 创建2D渲染器
  css2Renderer = new CSS2DRenderer()
  css2Renderer.setSize(window.innerWidth, window.innerHeight)
  css2Renderer.domElement.style.position = 'absolute'
  css2Renderer.domElement.style.top = '0px'
  css2Renderer.domElement.style.pointerEvents = 'none'

  // DOM 添加到页面
  const canvas = document.getElementById('canvas')
  canvas.appendChild(renderer.domElement)
  canvas.appendChild(css2Renderer.domElement)

  // 轨道控制器
  control = new OrbitControls(camera, renderer.domElement)
  control.update()

  // 坐标轴
  const axesHelper = new THREE.AxesHelper(1500)
  scene.add(axesHelper)
}

// 渲染循环
function renderLoop(t) {
  // 这里不再调用轨道控制器 update 方法，会影响摄像机 lookAt
  renderer.render(scene, camera)
  css2Renderer.render(scene, camera)
  EffectManager.getInstance().tickForEach(t)
  requestAnimationFrame(renderLoop)
}

// 灯光
function createLight() {
  // 基础光-环境光
  const ambientLight = new THREE.AmbientLight('#fff', 3)
  scene.add(ambientLight)
}

// 适配
window.addEventListener('resize', function () {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
  css2Renderer.setSize(window.innerWidth, window.innerHeight)
})

// 启动
window.addEventListener('DOMContentLoaded', function () {
  init()
  createLight()

  // 光线投射注册
  ClickHandler.getInstance().init(camera)

  // 创建天空背景
  new Sky(scene).setBack('/textures/sky/', ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'])

  // 模型加载器加载模型文件
  loadManager(['gltf/ship.glb', 'fbx/city.fbx'], modelList => {
    modelList.forEach(async modelObj => {
      if (modelObj.url === 'fbx/city.fbx') {
        // 城市模型文件
        const cityModelObj = new City(modelObj.model, scene, camera, control)
        const data = await DataManager.getInstance().getData()
        cityModelObj.dataObj = data

        EventBus.getInstance().on('pieClick', buildName => {
          let index = 0
          if (cityModelObj.lastOriginMat.length > 0 && cityModelObj.lastClick) {
            cityModelObj.lastClick.traverse(model => {
              model.material = cityModelObj.lastOriginMat[index++]
            })
          }
          const targetBuild = cityModelObj.model.getObjectByName(buildName)
          targetBuild.traverse(model => {
            if (model.type === 'Mesh') {
              cityModelObj.lastOriginMat.push(model.material)
              model.material = new THREE.MeshBasicMaterial({
                color: 0x0000ff
              })
              modifySelectCityMaterial(model)
            }
          })
          cityModelObj.lastClick = targetBuild
        })
        EventBus.getInstance().on('refreshHomeCount', data => {
          const buildName = data.fireBuilding.name
          if (buildName) {
            cityModelObj.initFire(buildName)
          }
        })
      } else if (modelObj.url === 'gltf/ship.glb') {
        // 轮船模型文件
        const shipModelObj = new Ship(modelObj.model, scene, camera, control)
        EffectManager.getInstance().addObj(shipModelObj)
        EventBus.getInstance().on('mode-roaming', isMove => {
          shipModelObj.control.enabled = !isMove
          shipModelObj.isCameraMove = isMove
        })
      }
    })

    // 生成飞行器对象
    const meshObj = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5), new THREE.MeshBasicMaterial({ color: 'lightblue' }))
    meshObj.visible = false
    const flyModelObject = new Fly(meshObj, scene, camera, control)
    EffectManager.getInstance().addObj(flyModelObject)
    EventBus.getInstance().on('mode-topView', isMove => {
      control.enabled = !isMove
      flyModelObject.isCameraMove = isMove
    })
    DataManager.getInstance().refreshData()
  })



  renderLoop()
})

